/*
 * Team Project 1: Database Implementation and Use
 * CPSC 315
 *
 * Class: Relation
 *
 * The Relation class utilizes DefaultTableModel to store a table of data
 * that can be queried by a Database.
 *
 * @author Justin Kern, Jill Greczek
 * */


import java.util.Vector;
import javax.swing.table.DefaultTableModel;


public class Relation extends DefaultTableModel {
    //EXCEPTIONS
    Exception NoSuchColumnException = new Exception("Column Does not exist.");
    Exception OutOfBoundsException = new Exception("Element access is out of bounds.");
    Exception NotCountableException = new Exception("Elements of this type cannot be counted");
    
    //DATA MEMBERS
    private String relationName;

    //CONSTRUCTORS
    public Relation(){
        //Create an empty relation
    }
    
    public Relation (String name){
        //Create an empty relation of name 'name'
    	relationName = name;
    }
    
    public Relation(String name, Vector data, Vector columnNames){
        //Create a relation where 'columnNames' are the names of the attributes
        //and 'data' is what is in the table.
    	setDataVector(data, columnNames);
    	relationName = name;
    }

    //METHODS 
    public String relationName(){
        //return the name of the relation
    	return relationName;
    }
    
    public void setRelationName(String name){
        //Set the 'relationName' data member
    	relationName = name;
    }
    
    public void insertTuple(Vector data){
        //insert a tuple into the relation
        addRow(data);
    }
    
    public Vector getColumn(int index){
        //returns a copy of the column at the given index
        Vector column = new Vector();
        //transfer all values of column index into vector column.
        for(int i = 0; i < this.getRowCount(); i++){
            column.add(((Vector)getDataVector().elementAt(i)).elementAt(index));
        }
        return column;
    }
    
    public boolean isColumnName(String name){
        //returns true if 'name' is a column name
        //iterates through the vector of column names and compares them to 'name'
        for(int i = 0; i < this.getColumnCount(); i++){
            if (this.getColumnName(i).equals(name))
                return true;
        }
        return false;
    }
    
    public int getColumnIndex(String name){
        //given the name of a column, returns the index of that column
        //returns -1 if column does not exist
        for(int i = 0; i < this.getColumnCount(); i++){
           try{ 
               if (this.getColumnName(i).equals(name))
                   return i;
               else
                   throw NoSuchColumnException;

           }
           catch(Exception e){
               System.out.println(e.getMessage());  
           }
        }
        return -1;
    }
    
    public Object getElement(int row, int column){
        //a simplified method for a complex call to the data vector
        //returns the element specified by row, column
        //if the element does not exist or the indices are out of bounds,
        //reuturns null.
        try{
            if ((getRowCount() >= row) && (getColumnCount() >= column)){
                return((Vector)getDataVector().elementAt(row)).elementAt(column);
            }
            else{
                throw OutOfBoundsException;
                
            }
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
        return null;
    }
    
    public boolean isElement(Object l){
        //returns true if Object l is an element of the Relation.
        //iterates through each element and compares it to l
        for (int i = 0; i < this.getColumnCount(); i++){
            for(int j = 0; j < this.getRowCount(); j++){
                if (this.getElement(j, i).equals(l)){
                    return true;
                }
            }
        }   
        return false;
    }
    
    public int count(){
        //returns the rumber of elements in a column
        return getRowCount();
    }
    
    public int max (int column){
        //returns the maximum value of a column specified by 'column'
        //if max is called on a column of strings, max throws an exception,
        //returns -1
        Integer test = 0;
        int max;
        try{
            if(getElement(0,column).getClass().equals(test.getClass())){
                max = (int) ((Integer) (getElement(0,column)));
                //iterate through each element and compare it to max
                //if temp is greater than max, set max equal to temp
                for(int i = 1; i < this.count(); i++){
                    int temp = (int) ((Integer)(getElement(i,column)));
                    if (temp > max){
                        max = temp;
                    }
                }
                return max;
            }
            else{
                throw NotCountableException;
            }
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
        return -1;
    }
    
    public int min(int column){
        //returns the minimum value of a column
        //if min is called on a column of strings, min throws an exception,
        //returns -1
        Integer test = 0;
        int min;
        try{
            if(getElement(0,column).getClass().equals(test.getClass())){
                min = (int) ((Integer) (getElement(0,column)));
                //iterate through each element and compare it to min
                //if temp is less than min, set min equal to temp
                for(int i = 1; i < this.count(); i++){
                    int temp = (int) ((Integer)(getElement(i,column)));
                    if (temp < min){
                        min = temp;
                    }
                }
                return min;
            }
            else{
                throw NotCountableException;
            }
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
        return -1;
    }
 
    public int sum(int column){
        //returns the sum of all elements in a column
        //throws NotCountableException and returns -1
        //if the objects are not of type int
        Integer test = 0;
        int sum;
        
        try{
            if(getElement(0,column).getClass().equals(test.getClass())){
                sum = (int) ((Integer) (getElement(0,column)));
                //iterate through each element of the colum and add it to sum
                for(int i = 1; i < this.count(); i++){
                    int temp = (int) ((Integer)(getElement(i,column)));
                    sum = sum + temp;
                }
                return sum;
            }
            else{
                throw NotCountableException;
            }
        }
        catch(Exception e){
            System.out.println(e.getMessage());
        }
        return -1;
    }
    
    public Vector getRow(int index){
        //returns the row specified by index in the form of a vector
        Vector row = new Vector();
        //iterate through each element in the row and add it to vector 'row'
        for(int i = 0; i < this.getColumnCount(); i++){
            row.add(this.getElement(index, i));
        }
        return row;
    }
    
}
